package sky.cin.framework.ioms.registry.center.entities;

import sky.cin.framework.extension.log.Croog;
import sky.cin.framework.ioms.common.entities.*;

import java.util.HashMap;
import java.util.Map;

public class MicroService {

    private String serviceName;
    private String host;
    private LoadBalance balance;
    private String domain;
    private Integer port;
    private Status status;
    private Croog log;
    private boolean heartBeat;
    private Map<String, InvokeInfo> invokeTarget = new HashMap<>();

    public MicroService(String serviceName, String host, String balance) {
        this.serviceName = serviceName;
        this.host = host;
        this.balance = LoadBalance.valueOf(balance.toUpperCase());
        String[] info = host.split(":");
        this.domain = info[0];
        this.port = Integer.valueOf(info[1]);
        this.status = Status.NORMAL;
        this.log = new Croog("sky.cin.framework.ioms.registry.center.entities.MicroService");
        new Thread(() -> {
            while (true) {
                sleep(15);
                if (!heartBeat) {
                    sleep(5);
                }
                if (heartBeat) {
                    if (this.status == Status.WARN) {
                        log.info(String.format("%s<%s> 恢复健康", serviceName, host));
                    }
                    this.status = Status.NORMAL;
                    this.heartBeat = false;
                } else {
                    if (this.status == Status.NORMAL) {
                        this.status = Status.WARN;
                        log.error(String.format("%s<%s> 心跳超时, 健康状态降级为 WARN", serviceName, host));
                    } else {
                        this.status = Status.ERROR;
                        log.error(String.format("%s<%s> 心跳仍然超时, 做宕机处理", serviceName, host));
                        break;
                    }
                }
            }
        }).start();
    }

    public void refresh() {
        heartBeat = true;
    }

    private void sleep(int seconds) {
        try {
            Thread.sleep(15 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public ServiceEndPoint select(String serviceName, Map<String, MicroService> msMap) {
        if (!invokeTarget.containsKey(serviceName)) {
            invokeTarget.put(serviceName, new InvokeInfo());
        }
        InvokeInfo invokeInfo = invokeTarget.get(serviceName);
        return invokeInfo.select(msMap, balance);
    }

    public String getServiceName() {
        return serviceName;
    }

    public void setServiceName(String serviceName) {
        this.serviceName = serviceName;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public LoadBalance getBalance() {
        return balance;
    }

    public void setBalance(LoadBalance balance) {
        this.balance = balance;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public Croog getLog() {
        return log;
    }

    public void setLog(Croog log) {
        this.log = log;
    }

    public boolean isHeartBeat() {
        return heartBeat;
    }

    public void setHeartBeat(boolean heartBeat) {
        this.heartBeat = heartBeat;
    }

    public Map<String, InvokeInfo> getInvokeTarget() {
        return invokeTarget;
    }

    public void setInvokeTarget(Map<String, InvokeInfo> invokeTarget) {
        this.invokeTarget = invokeTarget;
    }

    public boolean dead() {
        return this.status == Status.ERROR;
    }

    @Override
    public String toString() {
        return "MicroService{" +
                "serviceName='" + serviceName + '\'' +
                ", host='" + host + '\'' +
                '}';
    }
}
